<?php

/**
 * User: day
 * Date: 2018/09/04
 * Time: 10:31
 * Description:
 * AG API接入
 * 文档中允许根据时间范围来获取数据的 API 除報表統計的 API 外,都只能获取 10 分钟以内的数据
 * API 重复调用频率限制 15 秒只能调用 1 次
 */

namespace App\Console\Commands\ThirdOrder;


use App\Services\ThirdAPI\GameApiService;
use App\Services\ThirdAPI\AGAPIService;
use App\Services\UserService;
use common\utils\RedisKeys;
use Illuminate\Support\Facades\Redis;
use common\utils\SysCode;


class AGOrderProcessor extends BaseOrderProcessor
{
    protected $signature = self::PREFIX . 'ag {--type=}';
    protected $description = 'AG注单拉取';

    public $gameNames;
    public $agService;
    // 拉取注单的区间长度，比如从 4:00 - 5:00 一个小时的长度，根据注单量调整
    public $timeInterval = 60 * 10;
    // 自动重拉更新锁 redis key
    public $lockRedisKey = RedisKeys::AG_LOCK_AUTOFIX;
    // 拉取注单更新时间 redis key
    public $updateRedisKey = RedisKeys::AG_UPDATE_TIME;
    // 当前最新的拉取注单更新时间
    public $latestUpdateKey;

    // AG 内有多个游戏，比如捕鱼，YoPlay，真人视讯等，他们都是不同的接口来拉取注单的
    public $gameType;
    // 电子游戏注单类型
    public static $slotTypeName = [
        1 => '普通遊戲',
        2 => '免費遊戲',
        8 => '派對巨獎',
        9 => '瘋轉 Jackpot 遊戲',
        10 => '派對紅利',
        11 => '個人紅利'
    ];
    // (账单类型记录打鱼场景结算记录(Billtype=1)，中奖记录(Billtype=2)，买鱼账单(Billtype=4)，场景结束第一名奖励记录 (Billtype=7), 养鱼结算账单(Billtype=12)，
    public static $fishBillType = [
        1 => '打鱼场景结算记录',
        2 => '中奖记录',
        4 => '买鱼账单',
        7 => '第一名奖励',
        12 => '养鱼结算账单',
    ];

    /**
     * 初始化信息，子类需要重写这个方法
     */
    public function init($argv = null)
    {
        if (!$this->option('type')) {
            return error_exit(SysCode::INTERNAL_SERVER_ERROR, "AG 拉取的游戏类型未定义。");
        }
        $type = $this->option('type');
        // 必须调用父类init，初始化公共信息

        parent::init();
        $this->agService = new AGAPIService();

        // 5.第三方 partner id，名字，对应第三方表id
        $this->partnerName = "AG";
        $info = GameApiService::getApiPartnerInfoByName($this->partnerName);

        $this->partnerID = $info['id'];
        $this->gameNames = $this->agService->getGames();
        $this->playTypeNames = $this->agService->getPlayTypes();

        $this->userInfos = [];
        if ($type == 'slot' || $type == 'yoplay' || $type == 'fish' || $type == 'buyfish') {
            $this->orderType = self::ORDER_TYPE_EGAME;
        } elseif ($type == 'video') {
            $this->orderType = self::ORDER_TYPE_LIVE;
        }
        $this->gameType = $type;
    }

    /**
     * 向第三方API抓取数据
     */
    public function catchData()
    {

        $startTime = OrderStrategy::getUpdateKey($this->lockRedisKey, $this->updateRedisKey . $this->gameType);
        $startTime = strtotime($startTime);
        // 拉取 $this->timeInterval 的数据，减3秒是防止出现临界数据
        $this->latestUpdateKey = $endTime = min(time(), $startTime + $this->timeInterval - 3);
        $data = $this->agService->getAGOrders($this->gameType, $startTime, $endTime);
        return $data;
    }

    /**
     * 处理数据
     * 不可以放复杂操作，因为拉取到的每个数据都会经过 load 加载
     */
    public function load($data)
    {
        $this->createTime = date('Y-m-d H:i:s');
        switch ($this->gameType) {
            case 'slot':
            case 'yoplay':
                $this->slotOrders($data);
                break;
            case 'fish':
                $this->fishOrders($data);
                break;
            case 'buyfish':
                $this->buyFish($data);
                break;
            case 'video':
                $this->videoOrders($data);
                break;
            default:
                return error_exit(SysCode::INTERNAL_SERVER_ERROR, "未定义有效的游戏类型");
        }
        $this->originData = json_encode($data);
    }

    /**
     * 电子游戏注单处理
     * 投注額即為有效投注額
     * 8=派對巨獎:
     * <row billno="8180729033460211" slottype="8" account="0" cus_account="3445" valid_account="0" account_base="0" account_bonus="0" cus_account_base="0" cus_account_bonus="3445" src_amount="2995.600000" dst_amount="" flag="1" platformtype="SLOT" exttxid=""/>
     * 11=個人紅利:
     * <row billno="8180831173219022" slottype="11" account="0" cus_account="960" valid_account="0" account_base="0" account_bonus="0" cus_account_base="960" cus_account_bonus="0" src_amount="3170" dst_amount="" flag="1" platformtype="SLOT" exttxid=""/>
     */
    public function slotOrders($data)
    {
        $this->betContent = "";
        // billno:電子游戲訂單號
        $this->orderNumber = $data['billno'];
        // productid:訂單所屬產品 ID，即 CAGENT
        // $data['productid'];
        // username:用戶名
        $this->apiUserName = $data['username'];
        // billtime:訂單下注時間,格式為 YYYY-MM-DD HH24:MI:SS
        $this->betTime = $data['billtime'];
        // reckontime:訂單結算時間,格式為 YYYY-MM-DD HH24:MI:SS
        $this->updateKey = $this->settleTime = $data['reckontime'];
        $this->reportTime = $data['billtime'] ?? $data['reckontime'];//电子报表，第三方后台使用billtime 美东时间
        // slottype 1=普通遊戲, 2=免費遊戲, 8=派對巨獎(Jackpot 中獎), 9=瘋轉 jackpot 遊戲(Jackpot 中獎), 10=派對紅利, 11=個人紅利
        $this->gameCode = $data['slottype'];
        // gametype:遊戲類型
        $this->gameName = $this->gameNames[$data['gametype']]['game_name'];
        if ($this->gameType == 'slot') {
            $this->gameName .= "_" . self::$slotTypeName[$this->gameCode];
        }
        // account :投注額度
        $this->betMoney = round(amount_format($data['account'], true), 0);
        // cus_account :派彩額度
        $this->winLossMoney = round(amount_format($data['cus_account'], true), 0);
        // valid_account:有效投注額度
        $this->validMoney = round(amount_format($data['valid_account'], true), 0);
        // 派奖金额
        $this->prizeMoney = $this->betMoney + $this->winLossMoney;
        // // account_base:普通投注額度, 扣除Jackpot彩池下注的金額；是玩家主动下注的吗？
        // round($data['account_base'] * 100, 0);
        // account_bonus:紅利投注額度 或 Jackpot 奖池投注额度
        $this->contributeMoney = intval(amount_format($data['account_bonus'], true), 0);
        // // cus_account_base:普通游戲派彩
        // round($data['cus_account_base'] * 100, 0);
        // cus_account_bonus :此為會員於JACKPOT 或 紅利獲得派彩的金額
        $this->bonusMoney = intval(amount_format($data['cus_account_bonus'], true), 0);
        // flag :訂單狀態,0 為未派彩 ,1 為已派彩
        $this->apiStatus = $data['flag'];
        $this->commonStatus = $this->apiStatus == 0 ? self::COMMON_STATUS_UNSETTLE : self::COMMON_STATUS_SETTLE;
        // // src_amount:原額度, 空值為該遊戲不支持回傳此數值
        // $data['src_amount'];
        // // dst_amount:更新後的額度, 空值為該遊戲不支持回傳此數值
        // $data['dst_amount'] = $attribute['dst_amount'];
        // // 投注幣種
        // $data['currency'];
        // // betIP :投注 IP
        // $data['betIP'];
        // // platformType:平臺類型,SLOT 為電子游戲廳
        // $data['platformType'] = $attribute['platformType'];
        // // exttxid: 副單號, 空值為該遊戲不支持回傳此數值
        // $data['exttxid'] = $attribute['exttxid'];
    }

    /**
     * 捕鱼注单处理
     */
    public function fishOrders($data)
    {
        $this->betContent = "";
        // <BillId>帐单 ID</BillId>
        $this->orderNumber = $data['BillId'];
        // <UserName>玩家名稱</UserName>
        $this->apiUserName = $data['UserName'];
        // <StartTime>场景开始时间(TimeStamp)</StartTime> 场景开始时间,采用 Unix TimeStamp 格式(整数) 
        $this->updateKey = $this->betTime = date("Y-m-d H:i:s", $data['StartTime']);
        // <EndTime>场景结束时间(TimeStamp)</EndTime> 场景结束时间, 采用 Unix TimeStamp 格式(整数) 
        $this->settleTime = $data['EndTime'];
        $this->reportTime = $data['EndTime'];//报表统计时间特殊处理 hunter EndTime  （特性JackPotComm）    养鱼使用 HuntedTime
        // 没有gameID相关字段
        $this->gameCode = 1;

        // <BillType>账单类型</BillType> 账单类型记录
        $this->gameName = self::$fishBillType[$data['BillType']];
        // <Cost>发射子弹额度</Cost> 
        $this->validMoney = $this->betMoney = round(amount_format($data['Cost'], true), 0);
        // <Earn>捕鱼收入额度</Earn> 
        // <SceneEx>捕鱼王奖励总计</SceneEx> 
        $this->prizeMoney = round(amount_format(($data['Earn'] + $data['SceneEx']), true), 0);
        $this->winLossMoney = $this->prizeMoney - $this->betMoney;
        // <JackPotComm> Jackpot 抽水</JackPotComm> 
        $this->contributeMoney = intval(amount_format($data['JackPotComm'], true));
        // <JpDraw>用户 Jackpot 抽奖</JpDraw> 
        $this->bonusMoney = intval(amount_format($data['JpDraw'], true));
        // 都是结算的账单，没有对应的字段
        $this->apiStatus = 1;
        $this->commonStatus = self::COMMON_STATUS_SETTLE;
        // <Items>
        // <RoomBet>倍场</RoomBet>
        // <Remark>5:69.1</Remark> (表示场景中了个 5 等奖多少钱)
        // <OperType>1</OperType> (DB: _id)
        // (為 1 表示是手机下单 , 0 为网页下单)
        // </Items>
    }

    /**
     * 养鱼注单处理
     * 疑问，捕鱼接口有以下状态的信息，可能包含了：买鱼账单(Billtype=4)，养鱼结算账单(Billtype=12); ans: 不包含
     * 會員所買的魚有被打死的時候才會產生結算的注單，如果魚還沒有死亡，還活著的話，是不會產生結算注單的哦。
     */
    public function buyFish($data)
    {
        $this->betContent = "";
        // <BillNo>注单 no</BillNo>
        $this->orderNumber = $data['BillId'];
        // <UserName>用户名</UserName> 
        $this->apiUserName = $data['UserName'];
        // <Time>帐单产生时间</Time> 
        $this->updateKey = $this->betTime = $data['Time'];
        $this->settleTime = $data['HuntedTime'];
        $this->reportTime = $data['HuntedTime'];

        $this->gameCode = 1;
        $this->gameName = "养鱼";
        // <FishCost>鱼的价值</FishCost> 會員購買了這條魚花了100人民幣
        // 投注額跟有效投注額通常是相同的意思
        $this->validMoney = $this->betMoney = round(amount_format($data['FishCost'], true), 0);
        // 魚死亡後回收的額度(收入) - 會員買魚的額度(支出) = 會員的輸贏
        $this->winLossMoney = $this->prizeMoney - $this->betMoney;
        // <BulletCostInFish>魚吃多少额度</ BulletCostInFish > 會員這條魚死掉後所獲得的收益。
        $this->prizeMoney = round(amount_format($data['BulletCostInFish'], true), 0);
        // 没有贡献和彩金
        $this->contributeMoney = 0;
        $this->bonusMoney = 0;
        // 都是结算的账单，没有对应的字段
        $this->apiStatus = $data['Flag'];
        $this->commonStatus = self::COMMON_STATUS_SETTLE;
    }

    /**
     * 视讯注单处理
     */
    public function videoOrders($data)
    {
        // 投注内容
        $this->betContent = $this->playTypeNames[$data['gameType'] . "_" . $data['playType']]['description'];
        // billNo:訂單號
        $this->orderNumber = $data['billNo'];
        // playName:用戶名
        $this->apiUserName = $data['playName'];
        // betTime:下注時間
        $this->betTime = $data['betTime'];
        // recalcuTime:派彩時間
        $this->updateKey = $this->settleTime = $data['recalcuTime'];
        $this->reportTime = $data['betTime'] ?? $data['recalcuTime'];//视讯报表统计字段
        $this->gameCode = $data['slottype'];
        // 游戏名
        $this->gameName = $this->gameNames[$data['gameType']]['game_name'];
        // gameCode:局號
        $this->gameCode = $data['gameCode'];
        // betAmount:投注額度
        $this->betMoney = round(amount_format($data['betAmount'], true), 0);
        // netAmount :派彩額度
        $this->winLossMoney = round(amount_format($data['netAmount'], true), 0);
        // validBetAmount:有效投注額度
        $this->validMoney = round(amount_format($data['validBetAmount'], true), 0);
        $this->prizeMoney = $this->betMoney + $this->winLossMoney;
        // 视讯没有贡献和彩金
        $this->contributeMoney = 0;
        $this->bonusMoney = 0;
        // flag :訂單狀態,0 為未派彩 ,1 為已派彩
        $this->apiStatus = $data['flag'];
        $this->commonStatus = $this->apiStatus == 0 ? self::COMMON_STATUS_UNSETTLE : self::COMMON_STATUS_SETTLE;

        // remark:注示
        // $subData['remark'] = $attribute['remark'];

        // // playType:玩法類型
        // $subData['playType'] = $attribute['playType'];
        // // beforeCredit:餘額
        // $subData['beforeCredit'] = $attribute['beforeCredit'];
        // // betIP :投注 IP
        // $subData['betIP'] = $attribute['betIP'];
        // // platformType:平臺類型為 AGIN
        // $subData['platformType'] = $attribute['platformType'];
        // // devicetype: 0 是 PC, 大於等於 1 是手機
        // $subData['devicetype'] = $attribute['devicetype'];
        // // currency :投注幣種
        // $subData['currency'] = $attribute['currency'];
        // // tablecode :桌台號
        // $subData['tablecode'] = $attribute['tablecode'];
    }

    /*
     * 更新redis拉取注单ID
     */
    public function updateFlag($updateKey)
    {
        $redis = Redis::connection();
        $redis->set($this->updateRedisKey . $this->gameType, date("Y-m-d H:i:s", $this->latestUpdateKey));
    }


    /**
     * 处理数据，每个子类需要根据第三方的单条数据内容来获取有用的信息
     */
    public function initFromData($data)
    {

    }

    /**
     * 修复数据内容，每个子类需要实现怎么修复数据内容
     */
    public function fixData($date)
    {

    }

}